package com.example.netdemo.base

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import com.example.netdemo.retrofit.Resource
import com.example.netdemo.viewmodel.LoadingState
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.lang.Exception

open class BaseViewModel : ViewModel() {
    private val _loadingState = MutableLiveData<LoadingState>()
    val loadingState : LiveData<LoadingState> get() = _loadingState

    private val compositeDisposable = CompositeDisposable()

    private val observers = mutableListOf<Observer<*>>()

    private fun showLoading(show: Boolean = true, message: String = "加载中...") {
        if (show) {
            _loadingState.postValue(LoadingState.Message(message))
        } else{
            _loadingState.postValue(LoadingState.Hide)
        }
    }

    fun hideLoading() {
        _loadingState.postValue(LoadingState.Hide)
    }

    protected fun <T> launchAndLoad(
        showLoading: Boolean = true,
        block: () -> LiveData<Resource<T>>
    ) : LiveData<Resource<T>> {
        val liveData =MutableLiveData<Resource<T>>()

        if (showLoading) {
            showLoading()
        }


        val result = block()

        val observer = object : Observer<Resource<T>> {
            override fun onChanged(resource: Resource<T>) {
                liveData.postValue(resource)
                if (resource !is Resource.Loading) {
                    hideLoading()
                    result.removeObserver(this)
                }
            }
        }

        try {
            result.observeForever(observer)
        } catch (e: Exception) {
            hideLoading()
            liveData.postValue(Resource.error(e.message ?: "未知错误"))
        }

        return liveData
    }

    fun addDisposable(disposable: Disposable) {
        compositeDisposable.add(disposable)
    }

    override fun onCleared() {
        super.onCleared()
        observers.clear()
        compositeDisposable.clear()
    }
}